#include "Main.h"

/*
  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/


///////////////////////////////////////////////////////////////////////////////
// Static arrays for file/directory properties
// Borrowed and modified from the d2jsp source (it WAS an opensource release, remember?)
// Misc rewrites, fix for readLine, misc additions by eLe
// Added in by lord2800
// Later completely rewritten by lord2800, none of it is directly from d2jsp code now
// revised again on 4/03/2004 by lord2800, now it's mad sexy
///////////////////////////////////////////////////////////////////////////////

enum {
	FILE_EOF,
	FILE_SIZE
};

static JSPropertySpec file_props[] = { 
	{"eof",		FILE_EOF,	JSPROP_ENUMERATE | JSPROP_READONLY},
	{"size",	FILE_SIZE,	JSPROP_ENUMERATE | JSPROP_READONLY},
	{0}
};

static JSFunctionSpec file_methods[] = {
	{"readLine",	readLine,	1},
	{"writeLine",	writeLine,	1},
	{"readline",	readLine,	1},
	{"writeline",	writeLine,	1},
	//{"read",		read,		1},
	{"write",		write,		1},
	{"seekline",	seekline,	1},
	{"seekLine",	seekline,	1},
	{"close",		closeFile,	0},
	{"flush",		flush,		0},
	{"remove",		deleteFile,	0},
	{0}
};

static JSClass file_class = {
    "file",	JSCLASS_HAS_PRIVATE,
    JS_PropertyStub, JS_PropertyStub, file_getProperty,
	JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
	JS_ConvertStub, file_finalize
};

enum {
	DIR_NAME,
	DIR_PATH
};

static JSPropertySpec dir_props[] = {
	{"name",	DIR_NAME,	JSPROP_READONLY | JSPROP_ENUMERATE},
	{"path",	DIR_PATH,	JSPROP_READONLY | JSPROP_ENUMERATE},
	{0}
};

static JSFunctionSpec dir_methods[] = {
	{"create",			dir_create,			1},
	{"remove",			dir_delete,			1},
	{"getFiles",		dir_getFiles,		1},
	{"getDirectories",	dir_getDirectories,	1},
	{0}
};

static JSClass directory_class = {
	"directory", JSCLASS_HAS_PRIVATE,
	JS_PropertyStub, JS_PropertyStub, dir_getProperty,
	JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub,
	JS_ConvertStub, dir_finalize
};

struct FileData
{
	FILE * fp;
	char * filename;
	char mode;
};


class DirData {
public:
	char name[_MAX_FNAME];
	char fullpath[_MAX_PATH];
	DirData(char* path, char* newname)
	{
		strcpy(name, newname);
		strcpy(fullpath, path);
	}
};

bool checkName(JSContext *cx, char *fn) {
	if(strstr(fn,"../") || strstr(fn,"..\\") || strstr(fn,"\"") || strstr(fn,"'") || strstr(fn,"%")) {
		JS_ReportError(cx, "Invalid name %s. Please correct this and re-run your script.", fn);
		return false;
	}
	return true;
}

// added for compatability and because I'm lazy, if someone goes over this later, you can remove the old checkFilename
// and replace it with checkName - lord2800
bool checkFilename(JSContext *cx, char* fn) {
	return checkName(cx, fn);
}

///////////////////////////////////////////////////////////////////////////////
//  openFile(string *FileName[, {int mode or char * mode}])  filename based on current path                                                         
//   Opens a file for reading, writing, or appending.                                                                       
//   0: Read			"r":  Read
//   1: Write			"w":  Write
//   2: Append			"a+": Append					By KypDuran
//												Rewritten by Ninjai			               
///////////////////////////////////////////////////////////////////////////////
JSBool openFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	// rewrite time.  Old code is preserved below:
	*rval = JSVAL_NULL; // default rval to null
	int mode = 0; // default to read
	int i = 0;
	char * modes[3] = {"r", "w", "a+"};
	char filename[_MAX_PATH];
	FILE * f;
	// input sanitization
	if(argc < 1 || argc > 2 || !JSVAL_IS_STRING(argv[0]) || !checkName(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0]))))
	{
		JS_ReportError(cx, InvalidParams, "fileOpen");
		return JS_TRUE;
	}
	if(argc == 2)
	{
		if(JSVAL_IS_INT(argv[1]))
		{
			mode = JSVAL_TO_INT(argv[1]);
			if(mode < 0 || mode > 2)
			{
				JS_ReportError(cx, InvalidIntParam, 2, mode);
				return JS_TRUE;
			}
		}
		else if(JSVAL_IS_STRING(argv[1]))
		{
			char * tmpmode = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
			for(i = 0; i < 3; i++)
			{
				if(!strncmp(modes[i], tmpmode, 1))
					break;
			}
			if(i == 3)
			{
				JS_ReportError(cx, InvalidStringParam, 2, tmpmode);
				return JS_TRUE;
			}
			else
				mode = i;
		}
		else
		{
			JS_ReportError(cx, InvalidIntParam, 2, JSVAL_TO_INT(argv[1]));
			return JS_TRUE;
		}
	}

	strncpy(filename, Vars.szPath, _MAX_PATH ); //Gets Current Directory of DLL
	strcat(filename, "\\scripts\\");
	strcat(filename,JS_GetStringBytes(JS_ValueToString(cx, argv[0]))); //gets filename

	f = fopen(filename, modes[mode]);
	if(!f)
		return JS_TRUE;
	
	FileData * ptFileData = new FileData;
	ptFileData->fp = f;
	ptFileData->mode = modes[mode][0];
	ptFileData->filename = new char[strlen(filename)+1];
	strcpy(ptFileData->filename, filename);
	JSObject *jsfile = JS_NewObject(cx, &file_class, NULL, NULL);
	if(!jsfile || !JS_DefineProperties(cx, jsfile, file_props) || !JS_DefineFunctions(cx, jsfile, file_methods)) 
	{
		delete ptFileData;
		return JS_TRUE;
	}
	
	JS_SetPrivate(cx, jsfile, ptFileData);
	*rval = OBJECT_TO_JSVAL(jsfile);
	return JS_TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// C++: seekline
// JS: fileobj.seekline/seekLine(int line)
// args: 1
//
// Moves the file pointer to a specified line
//
// Rewritten by eLe
// Added by lord2800
///////////////////////////////////////////////////////////////////////////////
JSBool seekline(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	*rval = BOOLEAN_TO_JSVAL(false);

	FileData * ptFileData = (FileData*)JS_GetPrivate(cx, obj);
	if(!ptFileData || !ptFileData->fp || ptFileData->mode == 'w') 
		return JS_TRUE;
	if(!JSVAL_IS_INT(argv[0])) 
		return JS_TRUE;

	int line = JSVAL_TO_INT(argv[0]);
	char c;
	long pos;
	fseek(ptFileData->fp, 0, SEEK_SET);
	for (int i = 1; i < line; i++)
	{
		do {
			pos = ftell(ptFileData->fp);
			c = fgetc(ptFileData->fp);
		} while ((c != '\r') && (c != '\n') && !feof(ptFileData->fp));
		fseek(ptFileData->fp, pos, SEEK_SET);
		if (!feof(ptFileData->fp))
			if (fgetc(ptFileData->fp) == '\r')
				fgetc(ptFileData->fp);
	}

	*rval = BOOLEAN_TO_JSVAL(true);
	return JS_TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// C++: closeFile
// JS: fileobj.close()
// args: 0
//
// Closes the file the method is on
//
// Added by lord2800
///////////////////////////////////////////////////////////////////////////////
JSBool closeFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	*rval = BOOLEAN_TO_JSVAL(false);

	FileData * ptFileData = (FileData *)JS_GetPrivate(cx, obj);
	if(!ptFileData || !ptFileData->fp)
		return JS_TRUE;
	
	fclose(ptFileData->fp);
	ptFileData->fp = NULL;

	*rval = BOOLEAN_TO_JSVAL(true);
	return JS_TRUE;
}

///////////////////////////
// C++: readLine
// JS: fileobj.readLine()
// args: 0
//
// returns a line from the file pointer, not including \r or \n at the end
//
// Fixed by eLe - FINALLY WORKING THE WAY WE WANT IT! DON'T TOUCH IT!
// Changed and damaged by Ninjai
// Original by lord2800
JSBool readLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{

	*rval = STRING_TO_JSVAL(NULL);

	int nBuf = 0;
	fpos_t * position = new fpos_t;
	char c;
	
	FileData * ptFileData = (FileData *)JS_GetPrivate(cx, obj);
	if(!ptFileData || !ptFileData->fp) 
		return JS_TRUE;

	fgetpos(ptFileData->fp, position);
	do 
	{
		c = fgetc(ptFileData->fp);
		nBuf++;
	} while ((c != '\r') && (c != '\n') && !feof(ptFileData->fp));

	char * buf = new char[nBuf+1];
	fsetpos(ptFileData->fp, position);
	fgets(buf, nBuf, ptFileData->fp);

	if (!feof(ptFileData->fp))
		if (fgetc(ptFileData->fp) == '\r')
			fgetc(ptFileData->fp);

	*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx,buf));

	delete[] buf;
	delete position;
	
    return JS_TRUE;
}

///////////////////////////
// C++: read
// JS: fileobj.read(int numchars)
// args: 1
// returns: the number of bytes read
//
// reads numchars from the file pointer
//
// Added by eLe

// FUCKS UP
JSBool read(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	*rval = STRING_TO_JSVAL(NULL);
	
	FileData * ptFileData = (FileData *)JS_GetPrivate(cx, obj);
	if(!ptFileData || !ptFileData->fp) 
		return JS_TRUE;

	if (argc < 1)
		return JS_TRUE;

	int numchars = JSVAL_TO_INT(argv[0]);
	char * buf = new char[numchars];
	fread(buf, sizeof(char), numchars, ptFileData->fp);

	*rval = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buf));

	delete buf;
	
    return JS_TRUE;
}

///////////////////////////
// C++: writeLine
// JS: fileobj.writeLine(string, bool)
// args: 2: the string to be written, and a boolean value to indicate if \r\n should be added
//
// writes a line to the file pointer and optionally adds \r\n (win32 newline)
//
// eLe: added optional \r\n
// Original by lord2800
JSBool writeLine(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{

	*rval = BOOLEAN_TO_JSVAL(false);

	FileData * ptFileData = (FileData *)JS_GetPrivate(cx, obj);
	if(!ptFileData || !ptFileData->fp) 
		return JS_TRUE;

	if(fputs(JS_GetStringBytes(JS_ValueToString(cx, argv[0])), ptFileData->fp) == EOF)
		return JS_TRUE;
	if (argc < 2 || ((argc > 1) && (JSVAL_TO_INT(argv[1]) == 1)))
		if (fputs("\r\n", ptFileData->fp) == EOF) 
			return JS_TRUE;

	*rval = BOOLEAN_TO_JSVAL(true);
	return JS_TRUE;
}

///////////////////////////
// C++: write
// JS: fileobj.write(string)
// args: 1
//
// writes a string to the file pointer
//
// Added by eLe and fixed by Sheppard

JSBool write(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	*rval = STRING_TO_JSVAL(NULL);
	
	FileData * ptFileData = (FileData *)JS_GetPrivate(cx, obj);
	if(!ptFileData || !ptFileData->fp) 
		return JS_TRUE;

	if (argc < 1)
		return JS_TRUE;

	CHAR szBuffer[8192] = "";
	CHAR* buf = szBuffer;

	strcpy(buf, JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
	while ((*buf != '\0') && fputc(*(buf++), ptFileData->fp) != EOF);

	*rval = BOOLEAN_TO_JSVAL(true);
	
    return JS_TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// C++: deleteFile
// JS: fileobj.remove()
// args: 0
//
// Deletes the file the object is on
//
// Added by lord2800
///////////////////////////////////////////////////////////////////////////////
JSBool deleteFile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	FileData * ptFileData = (FileData *)JS_GetPrivate(cx, obj);
	if(!ptFileData || !ptFileData->fp) 
		return JS_TRUE;

	fclose(ptFileData->fp);
	ptFileData->fp = NULL;
	remove(ptFileData->filename);
	delete ptFileData;

	return JS_TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// C++: flush
// JS: fileobj.flush()
// args: 0
//
// Flushes all remaining data to the pointer
//
// Added by lord2800
///////////////////////////////////////////////////////////////////////////////
JSBool flush(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	*rval = BOOLEAN_TO_JSVAL(false);
	FileData * ptFileData = (FileData *)JS_GetPrivate(cx, obj);
	if(!ptFileData || !ptFileData->fp) 
		return JS_TRUE;

	if(fflush(ptFileData->fp)) 
		*rval = BOOLEAN_TO_JSVAL(true);
	return JS_TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// C++: file_getProperty
// JS: N/A (called by getting property)
// args: N/A
//
// Gets the value of the specified property
//
// Added by lord2800
///////////////////////////////////////////////////////////////////////////////
JSBool file_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
	FileData * ptFileData = (FileData *)JS_GetPrivate(cx, obj);
	if(!ptFileData || !ptFileData->fp) 
		return JS_TRUE;

	if(JSVAL_IS_INT(id))
		switch(JSVAL_TO_INT(id))
		{
			case FILE_EOF:
				*vp = INT_TO_JSVAL(feof(ptFileData->fp));
				break;
			case FILE_SIZE:
				*vp = INT_TO_JSVAL(_filelength(_fileno(ptFileData->fp)));
				break;
		}
	return JS_TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// C++: file_finalize
// JS: N/A
// args: N/A
//
// N/A
//
// Added by lord2800
///////////////////////////////////////////////////////////////////////////////
void file_finalize(JSContext *cx, JSObject *obj)
{
	FileData * ptFileData = (FileData *)JS_GetPrivate(cx, obj);
	if(ptFileData) 
	{
		if(ptFileData->fp)
		{
			fclose(ptFileData->fp);
			ptFileData->fp = NULL;
		}
		if(ptFileData->filename)
			delete ptFileData->filename;
		delete ptFileData;
	}
}

////////////////////////////////////////////////////////////////////////////////
// Directory stuff
////////////////////////////////////////////////////////////////////////////////

JSBool openDir(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	if(argc != 1) return JS_TRUE;
	char* path = new char[_MAX_PATH];
	char* fullpath = new char[_MAX_PATH];
	char* name = new char[_MAX_FNAME];
	strcpy(name, JS_GetStringBytes(JSVAL_TO_STRING(argv[0])));
	if(!checkName(cx, name)) { return JS_TRUE; }
	strcpy(path, Vars.szPath);
	strcat(path, "scripts\\");
	strcpy(fullpath, path);
	strcat(fullpath, name);
	if((_mkdir(fullpath) == -1) && (errno == ENOENT))
	{
		JS_ReportError(cx, "Couldn't get directory %s, path %s not found", JS_GetStringBytes(JSVAL_TO_STRING(argv[0])), path);
		return JS_TRUE;
	}
	else
	{
		JSObject *jsdir = JS_NewObject(cx, &directory_class, NULL, NULL);
		if(!JS_DefineProperties(cx, jsdir, dir_props)) return JS_TRUE;
		if(!JS_DefineFunctions(cx, jsdir, dir_methods)) return JS_TRUE;

		DirData* d = new DirData(path, name);
		JS_SetPrivate(cx, jsdir, d);
		*rval=OBJECT_TO_JSVAL(jsdir);
	}

	delete[] fullpath;

	return JS_TRUE;
}


////////////////////////////////////////////////////////////////////////////////
// dir_getFiles
// searches a directory for files with a specified extension(*.* assumed)
//
// Added by lord2800
////////////////////////////////////////////////////////////////////////////////

JSBool dir_getFiles(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{	
	if(argc > 1) return JS_TRUE;
	if(argc < 1) argv[0] = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, "*.*"));

	DirData* d = (DirData*)JS_GetPrivate(cx, obj);
	char* search = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));

	long hFile;
	char path[_MAX_PATH];
	strcpy(path, d->fullpath);
	strcat(path, d->name);
	char oldpath[_MAX_PATH];
	_getcwd(oldpath, _MAX_PATH);
	_chdir(path);
	_finddata_t found;
	if((hFile = _findfirst(search, &found)) == -1L)
		return JS_TRUE;
	else
	{
		jsint element=0;
		JSObject *jsarray = JS_NewArrayObject(cx, 0, NULL);
		jsval file;
		if(!(found.attrib & _A_SUBDIR))
		{
			file = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, found.name));
			JS_SetElement(cx, jsarray, element++, &file);
		}
		while(_findnext(hFile, &found) == 0)
		{
			if((found.attrib & _A_SUBDIR)) continue;
			file = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, found.name));
			JS_SetElement(cx, jsarray, element++, &file);
		}
		*rval=OBJECT_TO_JSVAL(jsarray);
	}
	_chdir(oldpath);
	return JS_TRUE;
}

JSBool dir_getDirectories(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	if(argc > 1) return JS_TRUE;
	if(argc < 1) argv[0] = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, "*.*"));

	DirData* d = (DirData*)JS_GetPrivate(cx, obj);
	char* search = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));

	long hFile;
	char path[_MAX_PATH];
	strcpy(path, d->fullpath);
	strcat(path, d->name);
	char oldpath[_MAX_PATH];
	_getcwd(oldpath, _MAX_PATH);
	_chdir(path);
	_finddata_t found;
	if((hFile = _findfirst(search, &found)) == -1L)
		return JS_TRUE;
	else
	{
		jsint element=0;
		JSObject *jsarray = JS_NewArrayObject(cx, 0, NULL);
		jsval file;
		if(!strcmp(found.name, ".") && !strcmp(found.name, "..") && (found.attrib & _A_SUBDIR))
		{
			file = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, found.name));
			JS_SetElement(cx, jsarray, element++, &file);
		}
		while(_findnext(hFile, &found) == 0)
		{
			if(!strcmp(found.name, "..") || !strcmp(found.name, ".") || !(found.attrib & _A_SUBDIR)) continue;
			file = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, found.name));
			JS_SetElement(cx, jsarray, element++, &file);
		}
		*rval=OBJECT_TO_JSVAL(jsarray);
	}
	_chdir(oldpath);
	return JS_TRUE;
}

JSBool dir_create(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	DirData* d = (DirData*)JS_GetPrivate(cx, obj);
	char* path = new char[_MAX_PATH];
	char* fullpath = new char[_MAX_PATH];
	char* name = new char[_MAX_FNAME];
	strcpy(name, JS_GetStringBytes(JSVAL_TO_STRING(argv[0])));
	strcpy(path, d->fullpath);
	strcat(path, d->name);
	strcat(path, "\\");
	strcpy(fullpath, path);
	strcat(fullpath, name);
	if(_mkdir(path) == -1)
	{
		if(errno == ENOENT)
		{
			JS_ReportError(cx, "Couldn't create directory %s, path %s not found", JS_GetStringBytes(JSVAL_TO_STRING(argv[0])), path);
		}
	}
	else
	{
		JSObject *jsdir = JS_NewObject(cx, &directory_class, NULL, NULL);
		if(!JS_DefineProperties(cx, jsdir, dir_props)) return JS_TRUE;
		if(!JS_DefineFunctions(cx, jsdir, dir_methods)) return JS_TRUE;

		DirData* d = new DirData(path, name);
		JS_SetPrivate(cx, jsdir, d);
		*rval=OBJECT_TO_JSVAL(jsdir);
	}

	delete path;
	delete fullpath;

	return JS_TRUE;
}
JSBool dir_delete(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	DirData* d = (DirData*)JS_GetPrivate(cx, obj);
	char* path = new char[_MAX_PATH];
	strcpy(path, d->fullpath);
	strcat(path, d->name);
	if(_rmdir(path) == -1)
	{
		if(errno == ENOTEMPTY)
			JS_ReportError(cx, "Tried to delete %s directory, but it is not empty or is the current working directory", path);
		if(errno == ENOENT)
			JS_ReportError(cx, "Path %s not found", path);
	}
	else
	{
		*rval=BOOLEAN_TO_JSVAL(true);
	}
	delete path;

	return JS_TRUE;
}

JSBool dir_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
{
	DirData* d = (DirData*)JS_GetPrivate(cx, obj);

	if(JSVAL_IS_INT(id))
		switch(JSVAL_TO_INT(id))
		{
			case DIR_NAME:
				*vp=STRING_TO_JSVAL(STRING_TO_JSVAL(JS_InternString(cx, d->name)));
				break;
			case DIR_PATH:
				*vp=STRING_TO_JSVAL(STRING_TO_JSVAL(JS_InternString(cx, d->fullpath)));
				break;
		}
	return JS_TRUE;
}

void dir_finalize(JSContext *cx, JSObject *obj)
{
	DirData* d = (DirData*)JS_GetPrivate(cx, obj);
	if(d) delete d;
}


///////////////////////////////////////////////////////////////////////////////
//  IniRead(filename, sectionname, keyname, default)                         //                                     
//                                                                           //
//  Oringal Credits: Jonathan Bennett <jon@hiddensoft.com>                   //
//  Embedded by: Glorfindel and Insolence                                    //              
///////////////////////////////////////////////////////////////////////////////
int my_iniread(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char *pFileName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
	static char lpszBuf[MAX_PATH];
	strcpy(lpszBuf,Vars.szPath);
	strcat(lpszBuf,pFileName);

    char   szBuffer[65535];        // Max ini file size is 65535 under 95

    char   *pSectionName = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
    char   *pKeyName = JS_GetStringBytes(JS_ValueToString(cx, argv[2]));
    char   *pDefault = JS_GetStringBytes(JS_ValueToString(cx, argv[3]));

    GetPrivateProfileString(pSectionName, pKeyName,
                     pDefault, szBuffer, 65535, lpszBuf);
   
    // Return the string   
    size_t length = strlen(szBuffer);

    *rval = STRING_TO_JSVAL(JS_NewStringCopyN(cx, szBuffer, length));

    // True
    return JS_TRUE;
}

///////////////////////////////////////////////////////////////////////////////
//  IniWrite(filename, sectionname, keyname, value)                          //                                     
//                                                                           //
//  Original Credits: Jonathan Bennett <jon@hiddensoft.com>                  //
//  Embedded by: Insolence                                                   //              
///////////////////////////////////////////////////////////////////////////////
int my_iniwrite(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	char *pFileName = JS_GetStringBytes(JS_ValueToString(cx, argv[0]));
	static char lpszBuf[MAX_PATH];
	strcpy(lpszBuf,Vars.szPath);
	strcat(lpszBuf,pFileName);

    char   *pSectionName = JS_GetStringBytes(JS_ValueToString(cx, argv[1]));
    char   *pKeyName = JS_GetStringBytes(JS_ValueToString(cx, argv[2]));
    char   *pValue = JS_GetStringBytes(JS_ValueToString(cx, argv[3]));
 
	// Get the fullpathname (ini functions need a full path) 

	if (WritePrivateProfileString(pSectionName, pKeyName, pValue, lpszBuf))
		WritePrivateProfileString(NULL, NULL, NULL, lpszBuf);	// Flush

	return JS_TRUE;

}